package com.mao.interview.lock;

import java.util.concurrent.atomic.AtomicReference;

/**
 * 一个标准CLH的自旋锁实现
 */
public class MyClhLock implements MyLock {

	private ThreadLocal<QNode> myNode;
	private ThreadLocal<QNode> preNode;
	private AtomicReference<QNode> tail = new AtomicReference<MyClhLock.QNode>(new QNode());

	public MyClhLock() {
		myNode = new ThreadLocal<MyClhLock.QNode>() {
			@Override
			protected QNode initialValue() {
				return new QNode();
			}

		};
		preNode = new ThreadLocal<MyClhLock.QNode>() {
			@Override
			protected QNode initialValue() {
				return null;
			}
		};
	}

	private static class QNode {
		volatile boolean isLocked = false;
	}

	@Override
	public void lock() {
		QNode n = myNode.get();
		n.isLocked = true;
		QNode pre = tail.getAndSet(n);
		preNode.set(pre);
		while (pre.isLocked) {/*
								 * spin logic, also a race condition with
								 * pre-node Thread
								 */
			// Thread.yield();
		}
	}

	/**
	 * 解锁线程会重置自己的myNode，让原来的myNode的状态变为liaojieunLock状态。
	 * 随后这个节点编程悬挂节点，没有线程引用为myNode，这个节点会让队头节点lock成功，即从while处返回
	 */
	@Override
	public void unlock() {
		QNode n = myNode.get();
		n.isLocked = false;
		QNode pre = preNode.get();
		myNode.set(pre);// 防止线程再次使用Lock上锁时，与后继节点的自旋判断那发生竞争
	}

}
